`timescale 1ns/1ps
`include "uvm_macros.svh"

import uvm_pkg::*;

`include "my_transaction.sv"
`include "my_sequence.sv"
`include "my_sequencer.sv"
`include "my_if.sv"
`include "my_driver.sv"
`include "my_monitor.sv"
`include "my_agent.sv"
`include "my_model.sv"
`include "my_scoreboard.sv"
`include "my_env.sv"

module top_tb;

reg             clk     ;
reg             rst_n   ;
reg   [7:0]     rxd     ;
reg             rx_dv   ;
wire  [7:0]     txd     ;
wire            tx_en   ;


// use the interface, instantiation a interface objection
my_if input_if  (clk,rst_n) ;
my_if output_if (clk,rst_n) ;

//use the "config_db" to map the input_if to the vif

initial begin
        uvm_config_db#(virtual my_if)::set(null , "uvm_test_top.i_agent.drv"  , "vif" , input_if);
        uvm_config_db#(virtual my_if)::set(null , "uvm_test_top.i_agent.mon"  , "vif" , input_if);
        uvm_config_db#(virtual my_if)::set(null , "uvm_test_top.o_agent.mon"  , "vif" ,output_if);
end

dut u_dut(
        .clk            ( clk                   ),
        .rst_n          ( rst_n                 ),
        .rxd            ( input_if.data         ),
        .rx_dv          ( input_if.valid        ),
        .txd            ( output_if.data        ),
        .tx_en          ( output_if.valid       )
);

//factory function don't need to new this function handly
//initial begin
//        my_driver       drv      ;
//        drv = new ("drv" , null );
//        drv.main_phase(null)     ;
//        $finish();  
//end

//this will call the factory function to new a object and auto run its main phase
initial begin
        run_test("my_env");
end



initial begin
  clk = 0 ;
  forever begin
    #100 clk = ~clk ;
  end
end

initial begin
  rst_n = 1'b0 ;
  #1000 ;
  rst_n = 1'b1 ;
end


initial begin
	$fsdbDumpfile("vcs_dump.fsdb");
	$fsdbDumpvars(0,top_tb);
end

endmodule
